La filosofia UNIX è una metodologia di sviluppo software proposta dal pioniere Ken Thompson (colui che, insieme a Dennis Ritchie, inventò il linguaggio C) che suggerisce l'adozione di programmazione modulare, uso di canali stanadard (stdout, stderr, ecc) e IPC oltre che all'uso delle pipe. È brevemente riassumibile con questa famosa citazione:
«Scrivete programmi che facciano una cosa e che la facciano bene. Scrivete programmi che funzionino insieme. Scrivete programmi che gestiscano flussi di testo, perché quella è un'interfaccia universale.»
- Peter H. Salus
L'importanza di questa strategia deriva dal fatto che in un sistema operativo, diversi processi potrebbero necessitare delle stesse strategie, e l'utilizzo di programmi modulari consente il massimo riutilizzo e la migliore efficienza possibile. Si pensi ai programmi come delle sezioni di un condotto, che vanno dall'input fino all'output. È possibile mescolare e modificare la catena nei suoi pezzi, lasciando inalterata la struttura rimanente.
Un'importantissima conseguenza dovuta all'adozione della filosofia UNIX è l'implementazione di programmi atomici, in grado di effettuare una singola operazione. Questo consente allo sviluppatore di costruire un software estremamente coerente e coeso, ottimizzato ed efficiente.
Di seguito vengono riportare le quattro regole fondamentali:
1. Fai fare a ciascun programma una cosa sola e bene. Per fare qualcosa di nuovo, costruisci un altro programma anziché complicare quello che esiste già introducendo nuove "feature".
2. Aspettati che l'output di ciascun programma diventi l'input di un altro, magari ancora sconosciuto.
3. Costituisci software, anche sistemi operativi, fatti in modo da essere testati presto nello sviluppo. Non esitare a buttare via le parti scadenti e a rifarle da zero.
4. Per alleggerire un compito di programmazione, è meglio usare gli strumenti anziché affidarsi a un aiuto non specializzato, anche se per creare gli strumenti è necessario fare una deviazione e ci si aspetta di buttarne via alcuni una volta terminato il loro utilizzo.
I programmi risultanti sono estremamente piccoli e specializzati, ma il complesso è elegante e di qualità.
Vediamo un esempio.
Supponiamo di avere un file access.log di un server Apache, le cui righe somigliano a qualcosa di questo tipo:
192.168.1.1 - - [07/Aug/2025:13:05:32 +0000] "GET /index.html HTTP/1.1" 200 2326
Proviamo questo comando:
cat access.log | cut -d' ' -f1 | sort | uniq -c | sort -nr | head -n 5
Cerchiamo di capire cosa fanno i vari comandi, i cui output sono concatenati all'input dei prossimi.
1. cat access.log legge il file access.log
2. cut -d ' -f1 intercetta l'output estraendo il primo campo (l'indirizzo IP, in questo esempio)
3. sort effettua l'ordinamento degli indirizzi collocando indirizzi uguali in spazi adiacenti
4. uniq -c conta gli IP ripetuti
5. sort -nr ordina gli elementi in ordine numerico decrescente (più frequenti di sopra)
6. head -n 5 mostra i primi 5 elementi
Questo comando mostra i primi 5 indirizzi IP che hanno avuto accesso alla risorsa. Come è ben facile intuire, è possibile interrompere o modificare a qualsiasi livello della catena il flusso di chiamate e restituire il risultato in stdout, rendendo la computazione straordinariamente flessibile ed elegante. Per fare una task non viene eseguito un megaprogramma, ne vengono eseguiti una moltitudine, ognuno "esperto" nel proprio ruolo.
Molti dei miei programmi rispecchiano la filosofia UNIX, che considero l'unica eternamente valida. Uno di questi è proprio il server di cui state usufruendo ora, che utilizza un parser Markdown -> HTML i cui dati vengono intercettati ed inviati da un webserver. Il codice è liberamente accessibile qui.Se volete usare il parser, può essere similarmente utilizzato a come abbiamo visto prima in questo modo:
cat file.md | mdparse